/*
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package botobjects;

import interfaces.BotObject;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TimeZone;

import main.CommonMethods;

import org.apache.log4j.Logger;

import tools.StringTools;
import database.DBConnectionFactory;

/**
 * This class represents contact info for a user
 * 
 * 
 */
public class ContactInfo implements BotObject {
   /**
    * Returns contact info for the specified user
    * 
    * @param searchFor
    * @return ContactInfo object. Returns null if no contact info is found
    */
   public static ContactInfo getContactInfo(final String searchFor) {
	  if (searchFor == null)
		 return null;
	  ContactInfo out = null;
	  PreparedStatement ps = null;
	  ResultSet rs = null;
	  try {
		 if (!"".equals(CommonMethods.getUserFromDB(searchFor, false))) {
			ps = DBConnectionFactory.getConnectionHandler().getConnection()
				  .prepareStatement("SELECT * FROM kdmember WHERE mainnick = ?");
		 } else {
			ps = DBConnectionFactory.getConnectionHandler().getConnection()
				  .prepareStatement("SELECT * FROM kdmemberarchive WHERE mainnick = ?");
		 }
		 ps.setString(1, searchFor);
		 rs = ps.executeQuery();
		 if (rs.next()) {
			Map<String, String> misc = new HashMap<String, String>();
			for (String s : rs.getString("misc").split("\n")) {
			   String[] temp = s.split("\t");
			   if (temp.length == 2) {
				  misc.put(temp[0], temp[1]);
			   }
			}
			out = new ContactInfo(rs.getString("mainnick"), rs.getDouble("timezone"), rs.getInt("dst"), rs.getString("country"),
				  rs.getString("realname"), "", false, misc);

			ps = DBConnectionFactory.getConnectionHandler().getConnection().prepareStatement("SELECT * FROM sms WHERE nick = ?");
			ps.setString(1, searchFor);
			rs = ps.executeQuery();

			if (rs.next()) {
			   out.setSmsAddy(rs.getString("mail"));
			   out.setSmsConfirmedWorking(rs.getBoolean("confirmed"));
			}
		 }
	  } catch (final SQLException e) {
		 Logger.getLogger("Error").error("", e);
	  } finally {
		 try {
			rs.close();
		 } catch (final Exception e) {
		 }
		 try {
			ps.close();
		 } catch (final Exception e) {
		 }
	  }
	  return out;
   }

   private String mainNick = "";
   private String newMainNick = null;
   private Double timeZone;
   private Integer dstIsActive;
   private String country;
   private String name;
   private String smsAddy;
   private Boolean smsConfirmedWorking = false;

   private Map<String, String> misc;

   public ContactInfo(final String mainNick) {
	  this(mainNick, null, null, null, null, null, false, null);
   }

   public ContactInfo(final String mainNick, final Double timeZone, final Integer dstIsActive, final String country,
		 final String name, final String smsAddy, final Boolean smsConfirmedWorking, final Map<String, String> misc) {
	  this.mainNick = mainNick;
	  this.timeZone = timeZone;
	  this.dstIsActive = dstIsActive;
	  this.country = country;
	  this.name = name;
	  this.smsAddy = smsAddy;
	  this.smsConfirmedWorking = smsConfirmedWorking;
	  this.misc = misc;
   }

   public String getCountry() {
	  return country;
   }

   public Integer getDstIsActive() {
	  return dstIsActive;
   }

   @Override
   public List<String> getIRCOutput(final int outputType, final String... args) {
	  List<String> out = new LinkedList<String>();
	  if (StringTools.isNullOrEmpty(getMainNick()) || getTimeZone() == null || getDstIsActive() == null || getCountry() == null
			|| getName() == null || getMisc() == null)
		 return out;
	  out.add(getMainNick() + " is " + getName() + " from " + getCountry());
	  String temp = "";
	  double d = getTimeZone() + getDstIsActive();
	  int i = (int) Math.floor(d);
	  if (Math.abs(i - d) < .0000001) {
		 temp = i > 0 ? "+" + i : String.valueOf(i);
	  } else {
		 temp = (i > 0 ? "+" + i : i) + ":30";
	  }
	  TimeZone tz = TimeZone.getTimeZone("GMT" + temp);
	  String pattern = "EEE, MMM d, H:mm:ss";
	  SimpleDateFormat sdf = new SimpleDateFormat(pattern, Locale.US);
	  sdf.setTimeZone(tz);
	  out.add(getMainNick() + "'s" + " local time is: " + sdf.format(new Date(Calendar.getInstance().getTimeInMillis())));

	  for (Entry<String, String> e : misc.entrySet()) {
		 if (!"".equals(e.getKey()) && !"".equals(e.getValue())) {
			out.add(getMainNick() + "'s " + StringTools.capitalizeFirstLetters(e.getKey()) + ": " + e.getValue());
		 }
	  }
	  return out;
   }

   public String getMainNick() {
	  return mainNick;
   }

   public Map<String, String> getMisc() {
	  return misc;
   }

   public String getName() {
	  return name;
   }

   public String getNewMainNick() {
	  return newMainNick;
   }

   @Override
   public Map<String, Object> getRPCOutput(final int... includes) {
	  Map<String, Object> out = new HashMap<String, Object>();
	  if (StringTools.isNullOrEmpty(getMainNick()) || getTimeZone() == null || getDstIsActive() == null || getCountry() == null
			|| getName() == null || getMisc() == null || getSmsAddy() == null || getSmsConfirmedWorking() == null)
		 return out;
	  out.put("Main Nick", getMainNick());
	  out.put("TimeZone", getTimeZone() == null ? 0.0 : getTimeZone());
	  out.put("DST", 1 == getDstIsActive() ? true : false);
	  out.put("Country", getCountry() == null ? "" : getCountry());
	  out.put("Name", getName() == null ? "" : getName());
	  out.put("SMS", getSmsAddy() == null ? "" : getSmsAddy());
	  out.put("SMS Working", getSmsConfirmedWorking());
	  out.put("Misc", getMisc() == null ? new HashMap<String, String>() : getTimeZone());
	  return out;
   }

   public String getSmsAddy() {
	  return smsAddy;
   }

   public Boolean getSmsConfirmedWorking() {
	  return smsConfirmedWorking;
   }

   public Double getTimeZone() {
	  return timeZone;
   }

   @Override
   public boolean saveToDB() {
	  boolean out = false;
	  if (StringTools.isNullOrEmpty(getMainNick()))
		 return out;
	  PreparedStatement ps = null;
	  ResultSet rs = null;
	  try {
		 if (getNewMainNick() != null && !getNewMainNick().equals(getMainNick()) && "".equals(getNewMainNick())) {
			ps = DBConnectionFactory.getConnectionHandler().getConnection()
				  .prepareStatement("UPDATE kdmember SET mainnick = ? WHERE mainnick = ?");
			ps.setString(1, getNewMainNick());
			ps.setString(2, getMainNick());
			ps.executeUpdate();
		 }
		 if (getTimeZone() != null) {
			ps = DBConnectionFactory.getConnectionHandler().getConnection()
				  .prepareStatement("UPDATE kdmember SET timezone = ? WHERE mainnick = ?");
			ps.setDouble(1, getTimeZone());
			ps.setString(2, getMainNick());
			ps.executeUpdate();
		 }
		 if (getDstIsActive() != null && (getDstIsActive() == 0 || getDstIsActive() == 1)) {
			ps = DBConnectionFactory.getConnectionHandler().getConnection()
				  .prepareStatement("UPDATE kdmember SET dst = ? WHERE mainnick = ?");
			ps.setInt(1, getDstIsActive());
			ps.setString(2, getMainNick());
			ps.executeUpdate();
		 }
		 if (getCountry() != null) {
			ps = DBConnectionFactory.getConnectionHandler().getConnection()
				  .prepareStatement("UPDATE kdmember SET country = ? WHERE mainnick = ?");
			ps.setString(1, getCountry());
			ps.setString(2, getMainNick());
			ps.executeUpdate();
		 }
		 if (getName() != null) {
			ps = DBConnectionFactory.getConnectionHandler().getConnection()
				  .prepareStatement("UPDATE kdmember SET realname = ? WHERE mainnick = ?");
			ps.setString(1, getName());
			ps.setString(2, getMainNick());
			ps.executeUpdate();
		 }
		 if (getSmsAddy() != null && getSmsConfirmedWorking() != null) {
			ps = DBConnectionFactory.getConnectionHandler().getConnection().prepareStatement("SELECT * FROM sms WHERE nick = ?");
			ps.setString(1, getMainNick());
			rs = ps.executeQuery();

			if (rs.next()) {
			   try {
				  ps.close();
			   } catch (final Exception e) {
			   }

			   ps = DBConnectionFactory.getConnectionHandler().getConnection()
					 .prepareStatement("UPDATE sms SET mail = ?, confirmed = ? WHERE nick = ?");
			   ps.setString(1, getSmsAddy());
			   ps.setBoolean(2, getSmsConfirmedWorking());
			   ps.setString(3, getMainNick());
			   ps.executeUpdate();
			} else {
			   try {
				  ps.close();
			   } catch (final Exception e) {
			   }

			   ps = DBConnectionFactory.getConnectionHandler().getConnection().prepareStatement("INSERT INTO sms VALUES(?,?,?)");
			   ps.setString(1, getMainNick());
			   ps.setString(2, getSmsAddy());
			   ps.setBoolean(3, getSmsConfirmedWorking());
			   ps.executeUpdate();
			}
		 }
		 if (getMisc() != null) {
			ps = DBConnectionFactory.getConnectionHandler().getConnection()
				  .prepareStatement("SELECT misc FROM kdmember WHERE mainnick = ?");
			ps.setString(1, getMainNick());
			rs = ps.executeQuery();

			if (rs.next()) {
			   List<String> categories = new LinkedList<String>();
			   String newMisc = "";
			   for (Entry<String, String> e : misc.entrySet()) {
				  categories.add(e.getKey().toLowerCase());
				  newMisc += e.getKey() + "\t" + e.getValue() + "\n";
			   }
			   String[] miscInfo = rs.getString("misc").split("\n");
			   for (String s : miscInfo) {
				  String[] temp = s.split("\t");
				  if (!categories.contains(temp[0].toLowerCase()) && !"".equals(s)) {
					 newMisc += s + "\n";
				  }
			   }
			   ps = DBConnectionFactory.getConnectionHandler().getConnection()
					 .prepareStatement("UPDATE kdmember SET misc = ? WHERE mainnick = ?");
			   ps.setString(1, newMisc);
			   ps.setString(2, getMainNick());
			   ps.executeUpdate();
			}
		 }
		 out = true;
	  } catch (final SQLException e) {
		 Logger.getLogger("Error").error("", e);
	  } finally {
		 try {
			ps.close();
		 } catch (final Exception e) {
		 }
	  }
	  return out;
   }

   public void setCountry(final String country) {
	  this.country = country;
   }

   public void setDstIsActive(final Integer dstIsActive) {
	  this.dstIsActive = dstIsActive;
   }

   public void setMisc(final Map<String, String> misc) {
	  this.misc = misc;
   }

   public void setName(final String name) {
	  this.name = name;
   }

   public void setNewMainNick(final String newMainNick) {
	  this.newMainNick = newMainNick;
   }

   public void setSmsAddy(final String smsAddy) {
	  this.smsAddy = smsAddy;
   }

   public void setSmsConfirmedWorking(final Boolean smsConfirmedWorking) {
	  this.smsConfirmedWorking = smsConfirmedWorking;
   }

   public void setTimeZone(final Double timeZone) {
	  this.timeZone = timeZone;
   }
}
